
const { finished } = require('stream')
const tool = require('../tools/tool')

const exp = {
    async getById(userExamCacheId) {
        let re = await tool.dbf().selectWithParams(`select * from userExamCache where id = ?`, [userExamCacheId])
        re = re[0]
        return await formatUserExamCacheItem(re)
    },
    async getLatestOneCache(userId) {
        let re = await tool.dbf().selectWithParams(`select * from userExamCache where userId = ? order by id desc limit 1`, [userId])
        re = re[0]
        return await formatUserExamCacheItem(re)
    },
    async getReDoById(userReDoId) {
        let re = await tool.dbf().selectWithParams(`select * from userReDoCache where id = ?`, [userReDoId])
        re = re[0]
        return await formatUserReDoCacheItem(re)
    },
    async getQuestionCacheById(isReDo = false, examOrReDoCacheId) {
        let re = await tool.dbf().selectWithParams(`select * from userQuestionCache where isReDo = ? and examOrReDoCacheId = ? order by id desc`, [isReDo ? 1 : 0, examOrReDoCacheId])
        for (let i = 0; i < re.length; i++) {
            re[i] = await formatUserQuestionCacheItem(re[i])
        }
        return re
    },
    async getLatestOneQuestionCache(isReDo = false, id) {
        let re = await tool.dbf().selectWithParams(`select * from userQuestionCache where isReDo = ? and examOrReDoCacheId = ? order by id desc limit 1`, [isReDo ? 1 : 0, id])
        re = re[0]
        return await formatUserQuestionCacheItem(re)
    },
    async getLatestOneReDoCache(userId) {
        let examCache = await this.getLatestOneCache(userId)
        let re = await tool.dbf().selectWithParams(`select * from userReDoCache where userExamCacheId = ? order by id desc limit 1`, [examCache.id])
        re = re[0]
        return await formatUserReDoCacheItem(re)
    },
    async addCache({
        userId,
        categoryId,
        paperId,
    }) {
        await tool.dbf().insertInto('userExamCache', {
            categoryId,
            paperId,
            userId,
            finished: 0,
            lastFinishedQuestionId: null,
            startAt: new Date(),
            score: null,
            reDoCount: 0
        })
    },
    updateCache: {
        async lastFinishedQuestionId(userExamCacheId, questionId) {
            await tool.dbf().updateById('userExamCache', userExamCacheId, {
                lastFinishedQuestionId: questionId
            })
        },
        async score(userExamCacheId, score) {
            let cacheInfo = await exp.getById(userExamCacheId)
            if (cacheInfo === undefined) throw '记录不存在'
            await tool.dbf().updateById('userExamCache', userExamCacheId, {
                score,
                endAt: (() => {
                    if (new Date(new Date() - new Date(cacheInfo.startAt)) > cacheInfo.paperInfo.duration * 60 * 1000) {
                        return new Date(new Date(cacheInfo.startAt) + cacheInfo.paperInfo.duration * 60 * 1000)
                    }
                    return new Date()
                })(),
                finished: 1,
            })
        },
        async addReDoCount(userExamCacheId, keywords) {
            let cacheInfo = await exp.getById(userExamCacheId)
            if (cacheInfo === undefined) throw '记录不存在'
            await tool.dbf().updateById('userExamCache', userExamCacheId, {
                reDoCount: cacheInfo.reDoCount + 1
            })
            await tool.dbf().insertInto('userReDoCache', {
                userExamCacheId,
                finished: 0,
                score: null,
                reDoCount: cacheInfo.reDoCount + 1,
                keywords,
                reDoQuestionCount: 0,
                reDoQuestionMaxCount: cacheInfo.paperInfo.isEssay ? (await tool.methods.settings().getItem('reDoEssayQuestionNum')) : (await tool.methods.settings().getItem('reDoNotEssayQuestionNum'))
            })
        }
    },
    updateReDoCache: {
        async score(userReDoCacheId, score) {
            let cacheInfo = await exp.getReDoById(userReDoCacheId)
            if (cacheInfo === undefined) throw '记录不存在'
            await tool.dbf().updateById('userReDoCache', userReDoCacheId, {
                score,
                finished: 1
            })
        },
        async addQuestionCount(userReDoCacheId) {
            let cache = await exp.getReDoById(userReDoCacheId)
            await tool.dbf().updateById('userReDoCache', cache.id, {
                reDoQuestionCount: cache.reDoQuestionCount + 1
            })
        }
    },
    async computeScore(isReDo = false, id) {
        let questions = []
        if (isReDo) {
            let userReDoCache = await exp.getReDoById(id)
            if (!userReDoCache) throw '重做记录不存在'
            let userExamCache = await exp.getById(userReDoCache.userExamCacheId)
            if (!userExamCache) throw '考试记录不存在'
            let questionCaches = await exp.getQuestionCacheById(true, id)
            if (userExamCache.paperInfo.isEssay) {
                for (let i = 0; i < questionCaches.length; i++) {
                    let currentQuestionCache = questionCaches[i]
                    // let ai_answer = await tool.openai.send(`请你给下面的申论题打一个分数，满分为100分，分数为整数，直接返回一个整数数字，不要带有其他字符。题干：${currentQuestionCache.questionInfo.stems}，
                    //     答案：${currentQuestionCache.questionInfo.answer}，
                    //     解析：${currentQuestionCache.questionInfo.analysis}，
                    //     用户提交的答案：${currentQuestionCache.answer.text}`)
                    // ai_answer = parseInt(ai_answer)
                    questions.push({
                        questionId: currentQuestionCache.questionId,
                        // score: isNaN(ai_answer) ? 0 : ai_answer,
                        score: currentQuestionCache.score,
                        questionCacheId: currentQuestionCache.id,
                    })
                }
            } else {
                for (let i = 0; i < questionCaches.length; i++) {
                    let currentQuestionCache = questionCaches[i]
                    questions.push({
                        questionId: currentQuestionCache.questionId,
                        score: (() => {
                            return currentQuestionCache.score
                            let checkRe = tool.isAnswerCorrect(currentQuestionCache.answer.options, currentQuestionCache.questionInfo.answer)
                            if (checkRe === 0) return 0
                            if (checkRe === 1) return 100
                            if (checkRe == 2) return 50
                        })(),
                        questionCacheId: currentQuestionCache.id,
                    })
                }
            }
        } else {
            let userExamCache = await exp.getById(id)
            if (!userExamCache) throw '考试记录不存在'
            let questionCaches = await exp.getQuestionCacheById(false, id)
            if (userExamCache.paperInfo.isEssay) {
                for (let i = 0; i < questionCaches.length; i++) {
                    let currentQuestionCache = questionCaches[i]
                    // let ai_answer = await tool.openai.send(`请你给下面的申论题打一个分数，满分为100分，分数为整数，直接返回一个整数数字，不要带有其他字符。题干：${currentQuestionCache.questionInfo.stems}，
                    //     答案：${currentQuestionCache.questionInfo.answer}，
                    //     解析：${currentQuestionCache.questionInfo.analysis}，
                    //     用户提交的答案：${currentQuestionCache.answer.text}`)
                    // ai_answer = parseInt(ai_answer)
                    questions.push({
                        questionId: currentQuestionCache.questionId,
                        // score: isNaN(ai_answer) ? 0 : ai_answer,
                        score: currentQuestionCache.score,
                        questionCacheId: currentQuestionCache.id,
                    })
                }
            } else {
                for (let i = 0; i < questionCaches.length; i++) {
                    let currentQuestionCache = questionCaches[i]
                    questions.push({
                        questionId: currentQuestionCache.questionId,
                        score: (() => {
                            return currentQuestionCache.score
                            let checkRe = tool.isAnswerCorrect(currentQuestionCache.answer.options, currentQuestionCache.questionInfo.answer)
                            if (checkRe === 0) return 0
                            if (checkRe === 1) return 100
                            if (checkRe == 2) return 50
                        })(),
                        questionCacheId: currentQuestionCache.id,
                    })
                }
            }
        }
        return questions
    },
    async getUserCategoryExamCache(userId, categoryId) {
        let re = await tool.dbf().selectWithParams(`select * from userExamCache where userId = ? and categoryId = ?`, [userId, categoryId])
        for (let i = 0; i < re.length; i++)re[i] = await formatUserExamCacheItem(re[i])
        return re
    },
    updateQuestionCache: {
        async add({
            questionId,
            userAnswer,
            isReDo,
            examOrReDoCacheId,
            score
        }) {
            let questionInfo = await tool.methods.question().getSingle(questionId)
            if (!questionInfo) throw '题目不存在'
            await tool.dbf().insertInto('userQuestionCache', {
                categoryId: questionInfo.categoryId,
                paperId: questionInfo.paperId,
                questionId,
                userAnswer: typeof userAnswer === 'string' ? userAnswer : JSON.stringify(userAnswer),
                isReDo: isReDo ? 1 : 0,
                examOrReDoCacheId,
                score
            })
            if (isReDo) await exp.updateReDoCache.addQuestionCount(examOrReDoCacheId)
        }
    },
    async getLastExamOrReDoWrongQuestions(userId) {
        let examCache = await this.getLatestOneCache(userId)
        if (!examCache) throw '没有考试记录'
        let arr = []
        if (examCache.reDoCaches.length) {
            arr = await tool.dbf().selectWithParams(`select * from userQuestionCache where isReDO = 1 and examOrReDoCacheId = ? and score != 100`, [examCache.reDoCaches[0].id])
        } else {
            arr = await tool.dbf().selectWithParams(`select * from userQuestionCache where isReDO = 0 and examOrReDoCacheId = ? and score != 100`, [examCache.id])
        }
        for (let i = 0; i < arr.length; i++)arr[i] = await formatUserQuestionCacheItem(arr[i])
        return arr
    },
    changeQuestionCachesToString(questionCachesArr) {
        let re = ''
        for (let i = 0; i < questionCachesArr.length; i++) {
            re += `第${i + 1}个错题（题目ID：${questionCachesArr[i].questionInfo.id}）：
            题干：${questionCachesArr[i].questionInfo.stems}
            类型：${questionCachesArr[i].questionInfo.type}
            ${questionCachesArr[i].questionInfo.type === '选择' ? (() => {
                    let re = '选项；'
                    re += `A: ${questionCachesArr[i].questionInfo.optionA}`
                    re += `B: ${questionCachesArr[i].questionInfo.optionB}`
                    re += `C: ${questionCachesArr[i].questionInfo.optionC}`
                    re += `D: ${questionCachesArr[i].questionInfo.optionD}`
                    return re
                })() : ''}
            解析：${questionCachesArr[i].questionInfo.analysis}
            用户提交的答案：${JSON.stringify(questionCachesArr[i].userAnswer)}
            题目关键词：${questionCachesArr[i].questionInfo.keywords}


            `
        }
        return re
    },
    async addReDoCache({
        userExamCacheId,
        reDoCount,
        keywords,
        reDoQuestionMaxCount
    }) {
        await tool.dbf().insertInto('userReDoCache', {
            userExamCacheId,
            reDoCount,
            keywords,
            reDoQuestionMaxCount,
            reDoQuestionCount: 0,
            score: 0,
            finished: 0
        })
    },
    selectQuestionCacheKeywords(questions) {
        let re = []
        for (let i = 0; i < questions.length; i++) {
            re = [...re, ...questions[i].questionInfo.keywords.split(',')]
        }
        return [...new Set(re)]
    },
    async reDoGetNextQuestion(userId) {
        try {
            let status = await tool.methods.chat().getStatus(userId)
            if (status.status !== 3) return undefined
            let reDoInfo = await tool.methods.exam().getLatestOneReDoCache(userId)
            let doneQuestions = await tool.dbf().selectWithParams(`select questionId from userQuestionCache where isReDo = 1 and examOrReDoCacheId = ?`, [reDoInfo.id])
            let keywords = reDoInfo.keywords
            let sql = `select * from question where `
            let sql2 = `select * from question where `
            for (let i = 0; i < doneQuestions.length; i++) {
                sql += ` id != ${doneQuestions[i].questionId} and `
            }
            sql += ' ( '
            for (let i = 0; i < keywords.length; i++) {
                if (i) sql += ' or '
                sql += ` keywords like '%${keywords[i]}%' `
                if (i) sql2 += ' or '
                sql2 += ` keywords like '%${keywords[i]}%' `
            }
            sql += ' ) '
            let total = (await tool.dbf().select(`select count(*) as total from (${sql}) as ft`))[0].total
            let questionStartIndex = tool.getRandomInt(total - 1)
            let questionItem = total === 0 ? [] : (await tool.dbf().select(`${sql} limit ${questionStartIndex},1`))
            questionItem = questionItem[0]
            if (questionItem == undefined) {
                let total2 = (await tool.dbf().select(`select count(*) as total from (${sql2}) as ft`))[0].total
                let questionStartIndex2 = tool.getRandomInt(total2 - 1)
                let questionItem2 = await tool.dbf().select(`${sql2} limit ${questionStartIndex2},1`)
                questionItem2 = questionItem2[0]
                if (questionItem2 === undefined) {
                    return undefined
                } else {
                    return await tool.methods.question().getSingle(questionItem2.id)
                }
            } else {
                return await tool.methods.question().getSingle(questionItem.id)
            }
        } catch (error) {
            console.log(error)
        }

    }
}

module.exports = exp

async function formatUserExamCacheItem(item) {
    if (!item) return item
    item.createdAt_read = tool.formatTimeNew(new Date(item.createdAt))
    item.updatedAt_read = tool.formatTimeNew(new Date(item.updatedAt))
    item.userInfo = await tool.methods.user().getSingleInfo.byId(item.userId)
    item.categoryInfo = await tool.methods.category().getSingle(item.categoryId)
    item.paperInfo = await tool.methods.paper().getSingle.byId(item.paperId)
    item.startAt_read = tool.formatTimeNew(new Date(item.startAt))
    if (item.endAt) item.endAt_read = tool.formatTimeNew(new Date(item.endAt))
    item.reDoCaches = await (async () => {
        let re = await tool.dbf().selectWithParams(`select * from userReDoCache where userExamCacheId = ? order by id desc`, [item.id])
        for (let i = 0; i < re.length; i++)re[i] = await formatUserReDoCacheItem(re[i])
        return re
    })()
    return item
}

async function formatUserReDoCacheItem(item) {
    if (!item) return item
    item.createdAt_read = tool.formatTimeNew(new Date(item.createdAt))
    item.updatedAt_read = tool.formatTimeNew(new Date(item.updatedAt))
    item.keywords = item.keywords.split(',')
    return item
}

async function formatUserQuestionCacheItem(item) {
    if (!item) return item
    item.createdAt_read = tool.formatTimeNew(new Date(item.createdAt))
    item.updatedAt_read = tool.formatTimeNew(new Date(item.updatedAt))
    item.categoryInfo = await tool.methods.category().getSingle(item.categoryId)
    item.paperInfo = await tool.methods.paper().getSingle.byId(item.paperId)
    item.questionInfo = await tool.methods.question().getSingle(item.questionId)
    try {
        item.answer = JSON.parse(item.answer)
    } catch (error) {

    }
    return item
}